#pragma once
#include "Log.hpp"
#include "InetAddr.hpp"
#include "Socket.hpp"
#include <pthread.h>
#include <functional>
#include <memory>

using func_t = std::function<void(std::shared_ptr<sock::TcpSocket> ts, inetaddr::InetAddr client)>;

struct ThreadData
{
public:
    ThreadData(std::shared_ptr<sock::TcpSocket> ts, func_t callback, InetAddr client)
        :_ts(ts), _callback(callback), _client(client)
    {}

    
    std::shared_ptr<sock::TcpSocket> _ts;
    func_t _callback;
    InetAddr _client;
};

class TcpServer
{
private:
    static void* Routine(void* args)
    {
        pthread_detach(pthread_self());
        ThreadData* td = static_cast<ThreadData*>(args);
        td->_callback(td->_ts, td->_client);

        td->_ts->Close();


        // -------------测试网络 
        // std::string out;
        // td->_ts.Recv(&out);

        // std::cout << out << std::endl;

        return nullptr;
    } 

public:
    TcpServer(std::string ip, uint16_t port, func_t callback)
        :_ts(new sock::TcpSocket(ip, port))
        ,_callback(callback)
    {}

    void Start()
    {
        _ts->CreateSocket();
        _ts->BindSocket();
        _ts->Listen();
    }

    void Run()
    {
        

        while(true)
        {
            sockaddr_in peer;
            socklen_t p_len;
            int sockfd = _ts->Accept(&peer, &p_len);

            pthread_t tid;
            ThreadData* td = new ThreadData(std::make_shared<sock::TcpSocket>(sockfd), _callback, InetAddr(peer));
            pthread_create(&tid, nullptr, Routine, (void*)td);
        }
    }
private:
    std::shared_ptr<sock::TcpSocket> _ts;

    func_t _callback;
};